package system.task;

import framework.datatype.DataConvertBase;
import lombok.Getter;
import org.slf4j.LoggerFactory;
import system.task.config.TaskConfig;
import system.task.logger.TaskLoggerContext;
import system.task.logger.TaskLoggerImpl;
import system.task.logger.TaskLoggerSlf4jWriter;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 执行器上下文
 */
public class ExecutorContext extends DataConvertBase {

    /**
     * 获取运行ID
     */
    @Getter
    private final String runId;

    /**
     * 当前任务记录
     */
    @Getter
    private final Task task;
    /**
     * 日志写书器
     */
    @Getter
    private final TaskLogger logger;
    /**
     * 任务参数
     */
    @Getter
    private final Map<String, Object> param;
    /**
     * 是否有错误发生
     */
    @Getter
    private boolean isAbnormal = false;

    /**
     * 初始化
     *
     * @param task
     * @param logger
     * @param param
     */
    public ExecutorContext(Task task, TaskLogger logger, Map<String, Object> param, String runId) {
        this.task = task;
        this.logger = logger;
        this.param = param;
        this.runId = runId;
    }

    /**
     * 添加异常消息
     *
     * @param message
     */
    @Deprecated
    public void addAbnormal(String message) {
        this.logger.writeln(message);
        this.isAbnormal = true;
    }

    /**
     * 记录一个空行日志
     */
    public void logLine() {
        this.logger.writeln(System.lineSeparator());
    }

    /**
     * 记录一个空行日志(当启用时间时不记录时间)
     */
    public void logEmptyLine() {
        this.logger.write(System.lineSeparator());
    }

    /**
     * 记录一个消息日志
     *
     * @param message
     */
    public void logInfo(String message) {
        this.logger.writeln(message);
    }

    /**
     * 记录一个消息日志
     *
     * @param message
     * @param format
     */
    public void logInfo(String message, Object... format) {
        this.logger.writeln(message, format);
    }

    /**
     * 记录一个错误日志
     *
     * @param message
     */
    public void logError(String message) {
        this.logger.error(message);
        this.isAbnormal = true;
    }

    /**
     * 记录一个错误日志
     *
     * @param message
     */
    public void logError(String message, Object... format) {
        this.logger.error(message, format);
        this.isAbnormal = true;
    }

    /**
     * 记录一个错误日志
     *
     * @param throwable
     */
    public void logError(Throwable throwable) {
        this.logger.error(throwable.getMessage(), throwable);
        this.isAbnormal = true;
    }

    /**
     * 记录一个错误日志
     *
     * @param throwable
     * @param message
     */
    public void logError(String message, Throwable throwable) {
        this.logger.error(message, throwable);
        this.isAbnormal = true;
    }

    /**
     * 记录一个错误日志
     *
     * @param throwable
     * @param message
     */
    public void logError(String message, Throwable throwable, Object... format) {
        if (format.length > 0)
            this.logger.error(String.format(message, format), throwable);
        else
            this.logger.error(message, throwable);
        this.isAbnormal = true;
    }

    /**
     * 记录一个日志内容(仅内容写入)
     *
     * @param message
     */
    public void logContent(String message) {
        this.logger.write(message);
    }

    /**
     * 记录一个日志内容(仅内容写入)
     *
     * @param message
     */
    public void logContent(String message, String... format) {
        this.logger.write(message, format);
    }

    /**
     * 设置一个参数
     *
     * @param name
     * @param value
     */
    public void put(String name, Object value) {
        param.put(name, value);
    }

    /**
     * 获取一个参数
     *
     * @param name
     * @return
     */
    public Object get(String name, Object defaultValue) {
        Object v = this.loadDataValue(name);
        if (v == null)
            return defaultValue;
        return v;
    }

    /**
     * 获取一个参数
     *
     * @param name
     * @return
     */
    public Object get(String name) {
        return this.loadDataValue(name);
    }

    /**
     * 加载一个参数数据
     *
     * @param name
     * @return
     */
    @Override
    public Object loadDataValue(String name) {
        return this.param.get(name);
    }

    /**
     * 创建调试上下文
     *
     * @return
     */
    public static void debugContext(TaskExecutor executor,Map<String, Object> param) throws Exception {
        ExecutorContext context = debugContext();
        if (param != null) {
            param.forEach(context::put);
        }
        executor.run(context);
    }

    /**
     * 创建调试上下文
     *
     * @return
     */
    public static void debugContext(TaskExecutor executor) throws Exception {
        debugContext(executor,null);
    }

    /**
     * 创建调试上下文
     *
     * @return
     */
    public static ExecutorContext debugContext() {
        return debugContext(new HashMap<>());
    }

    /**
     * 创建调试上下文
     *
     * @return
     */
    public static ExecutorContext debugContext(Map<String, Object> param) {
        Task task = new Task();
        String runId = "debug" + UUID.randomUUID().toString().replace("-", "");
        TaskLoggerContext loggerContext = new TaskLoggerContext(new TaskConfig(), task, runId);
        loggerContext.getLogWriters().add(new TaskLoggerSlf4jWriter(LoggerFactory.getLogger("task.debug")));
        TaskLoggerImpl logger = new TaskLoggerImpl(loggerContext);
        return new ExecutorContext(task, logger, param, runId);
    }
}
